/*###################################################################*
#
# MP (Mitchell Pell) Base - CrossPlatform Base Utilities.
# Copyright (C) 2013  Mitchell Pell
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
####################################################################*/

#ifndef BASE_THREADED_H
#define BASE_THREADED_H

#include <boost/thread.hpp>

namespace mp_base
{
	typedef boost::shared_ptr<boost::thread> shpThread;

	class Threaded
	{
	public:
		Threaded(){m_stopRequested=false; m_thread.reset();}
		virtual ~Threaded()
		{
			if ( m_thread.get() != NULL )
			{
				m_stopRequested = true;
				
				m_thread->join();
				m_thread.reset();
			}
		}

		bool StartThread()
		{
			m_stopRequested = false;
			try
			{
				m_thread.reset(
					new boost::thread( boost::bind(
						&Threaded::ThreadProc, this ) ));
			}
			catch( boost::exception const&  ex )
			{
				//Handle Error

				//Clear thread
				m_thread.reset();
				//return failure
				return false;
			}
			//return success
			return true;

		}

		bool StopThread(bool wait=false)
		{
			long count = m_thread.use_count();
			if ( count > 0 )
			{
				m_stopRequested = true;
				if ( wait ){
					m_thread->join();
				}
				m_thread.reset();
				return true;
			}
			else
				return false;
		}

		/*! Operating thread */
		void ThreadProc()
		{
			m_stopRequested = false;
			ThreadInitialization();
			while(!m_stopRequested)
			{
				ThreadUpdate();
			}
			ThreadShutdown();
		}

		bool IsStopRequested(){return m_stopRequested;}

	protected:	

		virtual void ThreadInitialization() = 0;
		virtual void ThreadUpdate() = 0;
		virtual void ThreadShutdown() = 0;

		volatile bool	m_stopRequested;
		shpThread		m_thread;
	};
}
#endif